package com.abucloud.logbackdemo.exception;

import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.List;

@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {
    /**
     * 业务异常管理
     *
     * @param businessException
     * @return
     */
    @ExceptionHandler(value = BusinessException.class)
    public Resp<Object> bizExceptionHandler(BusinessException businessException) {
        log.error("业务异常！状态码是：{}，错误信息：{}",
                businessException.getErrorCode(),
                businessException.getErrorMsg());
        return Resp.error(businessException.getErrorCode(), businessException.getErrorMsg());
    }

    /**
     * hibernate-validator校验管理
     *
     * @param ex
     * @return
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Resp<Object> methodArgumentNotValidExceptionHandler(MethodArgumentNotValidException ex) {
        String bindingResultStr = getBindingResult(ex);
        log.error("参数不合法！{}", bindingResultStr);
        return Resp.error(400, bindingResultStr);
    }

    /**
     * 全局异常管理
     *
     * @param ex
     * @return
     */
    @ExceptionHandler(value = Exception.class)
    public Resp<Object> exceptionHandler(Exception ex) {
        log.error("系统开小差了", ex);
        return Resp.error(500, "系统开小差了");
    }

    /**
     * GET/POST请求方法错误的拦截器
     * 因为开发时可能比较常见,而且发生在进入controller之前,上面的拦截器拦截不到这个错误
     * 所以定义了这个拦截器
     */
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public Resp httpRequestMethodHandler(HttpRequestMethodNotSupportedException ex) {
        log.error("请求方式有误", ex);
        return Resp.error(405, "请求方式不支持");
    }

    /**
     * 拼接hibernate-validator异常信息
     *
     * @param ex
     * @return
     */
    public static String getBindingResult(MethodArgumentNotValidException ex) {

        StringBuilder errorInfoStringBuilder = new StringBuilder();

        BindingResult bindingResult = ex.getBindingResult();
        List<FieldError> fieldErrors = bindingResult.getFieldErrors();
        int size = bindingResult.getFieldErrors().size();
        for (int i = 0; i < size; i++) {
            // 只有一个元素或者是最后一个元素时
            if (size == 1 || i == size - 1) {
                FieldError lastFieldError = fieldErrors.get(i);
                errorInfoStringBuilder
                        .append(lastFieldError.getField())
                        .append(":")
                        .append(lastFieldError.getDefaultMessage());
                break;
            }
            // 其他元素处理
            FieldError fieldError = fieldErrors.get(i);
            errorInfoStringBuilder
                    .append(fieldError.getField())
                    .append(":")
                    .append(fieldError.getDefaultMessage())
                    .append("；");
        }
        return errorInfoStringBuilder.toString();
    }

}
